home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / ge_cool.lha / GE_COOL2.1 / src / String / char.C next >
C/C++ Source or Header  |  1992-05-18  |  18KB  |  484 lines

  1. //
  2. // Copyright (C) 1991 Texas Instruments Incorporated.
  3. //
  4. // Permission is granted to any individual or institution to use, copy, modify,
  5. // and distribute this software, provided that this complete copyright and
  6. // permission notice is maintained, intact, in all copies and supporting
  7. // documentation.
  8. //
  9. // Texas Instruments Incorporated provides this software "as is" without
  10. // express or implied warranty.
  11. //
  12. //
  13. // Created: MBN 04/04/89 -- Initial design and implementation
  14. // Updated: MBN 12/15/89 -- Made case-flag optional on is_equal, is_not_equal
  15. // Updated: LGO 01/05/90 -- Split into seperate files
  16. // Updated: MJF 05/22/90 -- Fixed is_eqaul to return properly
  17. // Updated: DLS 03/22/91 -- New lite version
  18. //
  19.  
  20. #include <cool/char.h>        // Include char* specification header file
  21.  
  22. #if defined(DOS)
  23. extern "C" {
  24. #include <ctype.h>        // Include character processing macros
  25. }
  26. #else
  27. #include <ctype.h>        // Include character processing macros
  28. #endif
  29.  
  30. //
  31. // These arrays map between lower and upper case with everything else mapping to
  32. // itself.  The mappings are based upon ascii character sequences.
  33. //
  34.  
  35. const char upcharmap[] = {                                       // Hex
  36.  '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', // 00
  37.  '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', // 08           
  38.  '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', // 10           
  39.  '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', // 18           
  40.  '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', // 20  !"#$%&'
  41.  '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', // 28 ()*+,-./
  42.  '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', // 30 01234567
  43.  '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', // 38 89:;<=>?
  44.  '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107', // 40 @ABCDEFG
  45.  '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', // 48 HIJKLMNO
  46.  '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', // 50 PQRSTUVW
  47.  '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137', // 58 XYZ[\]^_
  48.  '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107', // 60 `abcdefg
  49.  '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', // 68 hijklmno
  50.  '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', // 70 pqrstuvw
  51.  '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177', // 78 xyz{|}~ 
  52.  '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  53.  '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  54.  '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  55.  '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  56.  '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  57.  '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  58.  '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  59.  '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  60.  '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  61.  '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  62.  '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  63.  '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
  64.  '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  65.  '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  66.  '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  67.  '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  68.  };
  69.  
  70. const char downcharmap[] = {                                     // Hex
  71.  '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', // 00
  72.  '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', // 08           
  73.  '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', // 10           
  74.  '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', // 18           
  75.  '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', // 20  !"#$%&'
  76.  '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', // 28 ()*+,-./
  77.  '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', // 30 01234567
  78.  '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', // 38 89:;<=>?
  79.  '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', // 40 @ABCDEFG
  80.  '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', // 48 HIJKLMNO
  81.  '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', // 50 PQRSTUVW
  82.  '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', // 58 XYZ[\]^_
  83.  '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', // 60 `abcdefg
  84.  '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', // 68 hijklmno
  85.  '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', // 70 pqrstuvw
  86.  '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', // 78 xyz{|}~ 
  87.  '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  88.  '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  89.  '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  90.  '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  91.  '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  92.  '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  93.  '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  94.  '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  95.  '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  96.  '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  97.  '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  98.  '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
  99.  '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  100.  '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  101.  '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  102.  '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  103.  };
  104.  
  105. Boolean is_equal (const char* c1, const char* c2, Boolean case_flag) {
  106.   if (case_flag == SENSITIVE) {            // Case sensitive
  107.     for ( ; *c1 == *c2; c1++, c2++)        // For each character in string
  108.       if (*c1 == END_OF_STRING)            // If end of first string
  109.     return TRUE;                // Match found, return TRUE
  110.     return (*c1 == *c2) ? TRUE : FALSE;        // Return match result
  111.   }
  112.   else {                    // Case insensitive
  113.     for ( ; *c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2); c1++, c2++)
  114.       if (*c1 == END_OF_STRING)            // If end of first string
  115.     return TRUE;                // Match found, return TRUE
  116.     // Return match result
  117.     return (*c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2)) ? TRUE : FALSE;
  118.   }
  119. }
  120.  
  121.  
  122. Boolean is_not_equal (const char* c1, const char* c2, Boolean case_flag) {
  123.   return (!is_equal (c1, c2, case_flag));
  124. }
  125.  
  126.  
  127. Boolean is_equal_n (const char* c1, const char* c2, int n, Boolean case_flag) {
  128.   if (case_flag == SENSITIVE) {            // Case sensitive
  129.     for ( ; --n >= 0 && *c1 == *c2; c1++, c2++)    // For each character in string
  130.       if (*c1 == END_OF_STRING)            // If end of first string
  131.     return TRUE;                // Match found, return TRUE
  132.     return n<0;                         // Return match result
  133.   }
  134.   else {                    // Case insensitive
  135.     for ( ; --n >= 0 && *c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2);
  136.     c1++, c2++)
  137.       if (*c1 == END_OF_STRING)            // If end of first string
  138.     return TRUE;                // Match found, return TRUE
  139.     return n<0;                         // Return match result
  140.   }
  141. }
  142.  
  143.  
  144. Boolean is_ge (const char* c1, const char* c2, Boolean case_flag) {
  145.   if (case_flag == SENSITIVE) {            // Case sensitive
  146.     for (; *c1 == *c2; c1++, c2++)        // For each character in string
  147.       if (*c1 == END_OF_STRING)            // If end of first string
  148.     return TRUE;                // Match found, return TRUE
  149.     return (*c1 > *c2) ? TRUE : FALSE;        // Return match result
  150.   }
  151.   else {                    // Case insensitive
  152.     for (;*c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2); c1++, c2++)
  153.       if (*c1 == END_OF_STRING)            // If end of first string
  154.     return TRUE;                // Match found, return TRUE
  155.     // Return match result
  156.     return (TO_UPPER (*c1) > TO_UPPER (*c2)) ? TRUE : FALSE;
  157.   }
  158. }
  159.  
  160.  
  161. Boolean is_lt (const char* c1, const char* c2, Boolean case_flag) {
  162.   return (!is_ge (c1, c2, case_flag));
  163. }
  164.  
  165.  
  166. Boolean is_le (const char* c1, const char* c2, Boolean case_flag) {
  167.   if (case_flag == SENSITIVE) {            // Case sensitive
  168.     for (; *c1 == *c2; c1++, c2++)        // For each character in string
  169.       if (*c1 == END_OF_STRING)            // If end of first string
  170.     return TRUE;                // Match found, return TRUE
  171.     return (*c1 < *c2) ? TRUE : FALSE;        // Return match result
  172.   }
  173.   else {                    // Case insensitive
  174.     for (; *c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2); c1++, c2++) 
  175.       if (*c1 == END_OF_STRING)            // If end of first string
  176.     return TRUE;                // Match found, return TRUE
  177.     // Return match result
  178.     return (TO_UPPER (*c1) < TO_UPPER (*c2)) ? TRUE : FALSE;
  179.   }
  180. }
  181.  
  182.  
  183. Boolean is_gt (const char* c1, const char* c2, Boolean case_flag) {
  184.   return (!is_le (c1, c2, case_flag));
  185. }
  186.  
  187. // c_capitalize -- Capitalize all words in a string. A word is defined as
  188. //                 a sequence of characters separated by non-alphanumerics
  189. // Input:          Character string
  190. // Output:         Updated string
  191.  
  192. char* c_capitalize (char* s) {        // Capitalize each word in string
  193.   char* p = s;                // Point to beginning of string
  194.   for (;;) {                // Infinite loop
  195.     for (; *p && !isalnum(*p); p++);    // Skip to first alphanumeric
  196.     if (*p == END_OF_STRING)        // If end of string
  197.       return s;                // Return string
  198.     *p = TO_UPPER(*p);            // Convert character
  199.     while(*++p && isalnum (*p));    // Search for next word
  200.   }
  201. }
  202.  
  203.  
  204. // c_downcase -- Convert all alphabetical characters to lowercase
  205. // Input:        Character string
  206. // Output:       Updated string
  207.  
  208. char* c_downcase (char* s) {    // Convert entire string to lower case
  209.   char* p = s;            // Point to beginning of string
  210.   while (*p) {            // While there are still valid characters
  211.     if (isupper (*p))        // if this is upper case
  212.       *p = TO_LOWER (*p);    // convert to lowercase 
  213.     p++;            // Advance pointer
  214.   }
  215.   return s;            // Return reference to modified string
  216. }
  217.  
  218.  
  219.  
  220. // c_left_trim -- Removes any occurrence of the character(s) in "rem" from
  221. //                "str" that appear as a prefix to the string. The first
  222. //                non-matching character encountered terminates the remove
  223. //                operation and the rest of the string is copied intact.
  224. // Input:         Source string and token string
  225. // Output:        Modified string "str" (string modified in place)
  226.  
  227. char* c_left_trim (char* str, const char* rem) { // Trim prefix from string
  228.   char* result = str;
  229.   char* s;
  230.   register char c;
  231.   for (s=str; (c=*s) != END_OF_STRING; s++) {
  232.     register const char* r = rem;
  233.     register char t;
  234.     while ((t=*r++) != END_OF_STRING && t != c); // Scan for match
  235.     if (t == END_OF_STRING)             // If no match found
  236.       break;
  237.   }
  238.   if (s != result)                  // when characters trimed
  239.     while ((*result++ = *s++) != END_OF_STRING); // shift string down
  240.   return str;                      // Return pointer to string
  241. }
  242.  
  243.  
  244. // c_right_trim -- Removes any occurrence of the character(s) in "rem" from
  245. //                 "str" that appear as a suffix to the string. The first
  246. //                 non-matching character encountered terminates the remove
  247. //                 operation and the rest of the string is copied intact.
  248. // Input:          Source string and token string
  249. // Output:         Modified string "str" (string modified in place)
  250.  
  251. char* c_right_trim (char* str, const char* rem) { // Trim suffix from string
  252.   char* s = str + strlen(str) - 1;          // last character of str
  253.   for (; s >= str; s--) {
  254.     register const char* r = rem;
  255.     register char t;
  256.     register char c = *s;
  257.     while ((t=*r++) != END_OF_STRING && t != c); // Scan for match
  258.     if (t == END_OF_STRING)             // If no match found
  259.       break;
  260.   }
  261.   *(s+1) = END_OF_STRING;
  262.   return str;                      // Return pointer to string
  263. }
  264.  
  265.  
  266. // c_trim -- Removes any occurrence of the character(s) in "rem" from "str"
  267. // Input:    Source string and token string
  268. // Output:   Source string (string is modified in place)
  269.  
  270. char* c_trim (char* str, const char* rem) {    // Trim characters from string
  271.   char* s = str;
  272.   char* result = str;
  273.   register char c;
  274.   while ((c=*s++) != END_OF_STRING) {
  275.     register const char* r = rem;
  276.     register char t;
  277.     while ((t=*r++) != END_OF_STRING && t != c); // Scan for match
  278.     if (t == END_OF_STRING)             // If no match found
  279.       *result++ = c;
  280.   }
  281.   *result = END_OF_STRING;            // NULL terminate string
  282.   return str;                    // Return pointer to string
  283. }
  284.  
  285.  
  286. // c_upcase -- Convert all alphabetical characters to uppercase
  287. // Input:      Character string 
  288. // Output:     Updated string
  289. //
  290.  
  291. char* c_upcase (char* s) {    // Convert entire string to upper case
  292.   char* p = s;            // Point to beginning of string
  293.   while (*p) {            // While there are still valid characters
  294.     if (islower (*p))        // if this is lower case
  295.       *p = TO_UPPER (*p);    // convert to uppercase 
  296.     p++;            // Advance pointer
  297.   }
  298.   return s;            // Return reference to modified string
  299. }
  300.  
  301. // strfind -- finds the pattern in the source.  Sets start and
  302. // end accordingly and returns a pointer to the beginning of the
  303. // string found, or NULL.  Uses * to mean any number of any characters,
  304. // and ? to mean one of any character.  \? and \* are used in the 
  305. // pattern to look for the actual symbols ? and * in the source.
  306. // Finds the first occurance from the beginning of the source string.
  307. //
  308.  
  309.  
  310. const char* strfind (const char* string, const char* pattern,
  311.              long* start, long* end)
  312. {
  313.   const char* stringp = string;
  314.   const char* startp = string;
  315.   for (; *pattern != '\0'; pattern++, string++) {
  316.     if (*pattern == '\\') {            // Special case \* and \?
  317.       pattern++;
  318.       if (*pattern == '*' || *pattern == '?') {
  319.     if (*string != *pattern)
  320.       return NULL;
  321.       }
  322.       else if (*string != '\\')
  323.     return NULL;
  324.     }
  325.     else if (*pattern == '*') {
  326.       long endp;
  327.       pattern++;
  328.       if (*pattern == '\0')
  329.     goto match;
  330.       while (strfind(string, pattern, (long *)NULL, &endp) == NULL) {
  331.     if (*string++ == '\0')
  332.       return NULL;
  333.       }
  334.       startp = string;
  335.       string += endp;
  336.       goto match;
  337.     }
  338.     else if (*string == '\0')
  339.       return NULL;
  340.     else if ((*pattern != '?') && (*pattern != *string))
  341.       return NULL;
  342.   }
  343.   if (*string != '\0') return NULL;
  344.  match:                        // Match found
  345.   if (start != NULL) *start = startp - stringp;
  346.   if (end != NULL) *end = string - stringp;
  347.   return(startp);
  348. }
  349.  
  350.  
  351. // strrfind -- finds the pattern in the source.  Sets start and
  352. // end accordingly and returns a pointer to the beginning of the
  353. // string found, or NULL.  Uses * to mean any number of any characters,
  354. // and ? to mean one of any character.  \? and \* are used in the 
  355. // pattern to look for the actual symbols ? and * in the source.
  356. // Finds the last occurance from the end of the source string.
  357.  
  358.  
  359. static const char* _strrfind(const char* strstart,
  360.                  const char* string,
  361.                  const char* patstart,
  362.                  const char* pattern,
  363.                  long* end)
  364. {
  365.   const char* startp = string;
  366.   for (; pattern >= patstart; pattern--, string--) {
  367.     if (*pattern == '*') {        // '*' matches anything or nothing
  368.       --pattern;
  369.       if (pattern >= patstart && *pattern == '\\') { // Special case \*
  370.     if (string < strstart || *string != '*')
  371.       return NULL;
  372.       }
  373.       else {
  374.     const char* res;
  375.     if (pattern < patstart) {
  376.       string++;
  377.       goto match;
  378.     }
  379.     while ((res=_strrfind(strstart,string,patstart,pattern,end)) == NULL) {
  380.       if (--string < strstart)
  381.         return NULL;
  382.     }
  383.     startp = string;
  384.     string = res;
  385.     goto match;
  386.       }
  387.     }
  388.     else if (string < strstart)            // check end of string
  389.       return NULL;
  390.     else if (*pattern == '?') {            // '?' matches any character
  391.       if (pattern > patstart && *(pattern-1) == '\\') { // Special case \?
  392.     pattern--;
  393.     if (*string != '?')
  394.       return NULL;
  395.       }
  396.     }
  397.     else if (*pattern != *string)
  398.       return NULL;
  399.   }
  400.   if (++string != strstart) return NULL;
  401.  match:                        // Match found
  402.   *end = startp - strstart + 1;
  403.   return(string);
  404. }
  405.  
  406.  
  407. const char* strrfind (const char* string, const char* pattern,
  408.               long* start, long* end)
  409. {
  410.   long endp;
  411.   const char* res = _strrfind(string, string + strlen(string) - 1,
  412.                   pattern, pattern + strlen(pattern) - 1, &endp);
  413.   if (res != NULL) {
  414.     if (start != NULL) *start = res - string;
  415.     if (end != NULL) *end = endp;
  416.   }
  417.   return(res);
  418. }
  419.  
  420. // strndup -- creates a new string and copies everything between
  421. // zero and length of the given char* into it.  Returns the new
  422. // string.
  423. //
  424.  
  425. char* strndup (const char* s, long length) {
  426.   if (length<0) return(NULL);
  427.   char* ret = (char*) new char[length+1];
  428.   char* retp = ret;  
  429.   while(length-- > 0 && *s != END_OF_STRING)
  430.     *retp++ = *s++;
  431.   *retp = END_OF_STRING;
  432.   return(ret);
  433. }
  434.  
  435.  
  436. // strnremove -- removes everything between zero and end from 
  437. // the given string.  Returns a pointer to the new string.
  438.  
  439. char* strnremove (char* s, long end) {
  440.   int len = strlen(s);
  441.   if (end < 0 ) return(NULL);
  442.   if (end > len) end = len;
  443.   for(int ind=0; s[ind]=s[end]; ind++) end++;
  444.   return(s);
  445. }
  446.  
  447. //
  448. // strnyank -- the equivalent of doing a strndup and a strnremove.
  449. // Returns a char* to the copy of zero-end elements of the given string.
  450. // Modifies the given string by removing the zero-end elements.
  451. //
  452.  
  453. char* strnyank (char* s, long end) {
  454.   int len = strlen(s);
  455.   if (end>len) end=len;
  456.   long mark = end;
  457.   char* ret = (char*) new char[end+1];
  458.   if (end < 0) return(NULL);
  459.   for(int ind=0; ind <= len; ind++) {
  460.     if (ind<mark) ret[ind]=s[ind];
  461.     s[ind]=s[end];
  462.     end++;
  463.   }
  464.   ret[mark]=END_OF_STRING;
  465.   return(ret);
  466. }
  467.  
  468.  
  469. // reverse -- Reverse the order of the characters in char*
  470. // Input:     char* 
  471. // Output:    char* with character order reversed
  472.  
  473. void reverse (char* c) {        // Reverse the order of characters
  474.   int length = strlen (c);        // Number of characters in string
  475.   char temp;
  476.  
  477.   for (int i = 0, j = length-1;        // Counting from front and rear
  478.        i < length / 2; i++, j--) {    // until we reach the middle
  479.     temp = c[i];            // Save front character
  480.     c[i] = c[j];            // Switch with rear character
  481.     c[j] = temp;            // Copy new rear character
  482.   }
  483. }
  484.